(ns clj-kondo.impl.extract-java-members
  (:require [babashka.fs :as fs]
            [clj-kondo.core :as kondo]
            [clojure.java.io :as io]
            [clojure.string :as str]))

(def classes
  '["clojure.lang.IRef"
    "clojure.lang.ISeq"
    "clojure.lang.ITransientVector"
    "clojure.lang.Indexed"
    "clojure.lang.Iterate"
    "clojure.lang.Keyword"
    "clojure.lang.LazySeq"
    "clojure.lang.LineNumberingPushbackReader"
    "clojure.lang.LineNumberingPushbackReader"
    "clojure.lang.LongRange"
    "clojure.lang.MapEntry"
    "clojure.lang.MultiFn"
    "clojure.lang.Named"
    "clojure.lang.PersistentArrayMap"
    "clojure.lang.PersistentHashMap"
    "clojure.lang.PersistentHashSet"
    "clojure.lang.PersistentList"
    "clojure.lang.PersistentQueue"
    "clojure.lang.PersistentQueue"
    "clojure.lang.PersistentStructMap"
    "clojure.lang.PersistentTreeMap"
    "clojure.lang.PersistentTreeSet"
    "clojure.lang.PersistentVector"
    "clojure.lang.RT"
    "clojure.lang.Range"
    "clojure.lang.Ratio"
    "clojure.lang.Ratio"
    "clojure.lang.ReaderConditional"
    "clojure.lang.Repeat"
    "clojure.lang.Reversible"
    "clojure.lang.Seqable"
    "clojure.lang.Sequential"
    "clojure.lang.Sorted"
    "clojure.lang.Symbol"
    "clojure.lang.Volatile"
    "java.io.BufferedInputStream"
    "java.io.BufferedOutputStream"
    "java.io.BufferedReader"
    "java.io.BufferedWriter"
    "java.io.ByteArrayInputStream"
    "java.io.ByteArrayOutputStream"
    "java.io.Closeable"
    "java.io.Console"
    "java.io.DataInput"
    "java.io.DataInputStream"
    "java.io.DataOutput"
    "java.io.DataOutputStream"
    "java.io.EOFException"
    "java.io.File"
    "java.io.FileFilter"
    "java.io.FileInputStream"
    "java.io.FileNotFoundException"
    "java.io.FileOutputStream"
    "java.io.FileReader"
    "java.io.FileWriter"
    "java.io.FilenameFilter"
    "java.io.IOException"
    "java.io.InputStream"
    "java.io.InputStreamReader"
    "java.io.OutputStream"
    "java.io.OutputStreamWriter"
    "java.io.PipedInputStream"
    "java.io.PipedOutputStream"
    "java.io.PrintStream"
    "java.io.PrintWriter"
    "java.io.PushbackInputStream"
    "java.io.PushbackReader"
    "java.io.RandomAccessFile"
    "java.io.Reader"
    "java.io.SequenceInputStream"
    "java.io.StringReader"
    "java.io.StringWriter"
    "java.io.Writer"
    "java.lang.AbstractMethodError"
    "java.lang.Appendable"
    "java.lang.ArithmeticException"
    "java.lang.AssertionError"
    "java.lang.Boolean"
    "java.lang.Byte"
    "java.lang.CharSequence"
    "java.lang.Character"
    "java.lang.Class"
    "java.lang.ClassCastException"
    "java.lang.ClassLoader"
    "java.lang.ClassNotFoundException"
    "java.lang.Comparable"
    "java.lang.Double"
    "java.lang.Error"
    "java.lang.Exception"
    "java.lang.ExceptionInInitializerError"
    "java.lang.Float"
    "java.lang.IllegalArgumentException"
    "java.lang.IllegalStateException"
    "java.lang.IndexOutOfBoundsException"
    "java.lang.Integer"
    "java.lang.InterruptedException"
    "java.lang.Iterable"
    "java.lang.LinkageError"
    "java.lang.Long"
    "java.lang.Math"
    "java.lang.NullPointerException"
    "java.lang.Number"
    "java.lang.NumberFormatException"
    "java.lang.Object"
    "java.lang.Package"
    "java.lang.Process"
    "java.lang.ProcessBuilder"
    "java.lang.ProcessHandle"
    "java.lang.Runnable"
    "java.lang.Runtime"
    "java.lang.RuntimeException"
    "java.lang.Short"
    "java.lang.StackTraceElement"
    "java.lang.String"
    "java.lang.StringBuilder"
    "java.lang.System"
    "java.lang.Thread"
    "java.lang.ThreadDeath"
    "java.lang.Throwable"
    "java.lang.UnsupportedOperationException"
    "java.lang.VirtualMachineError"
    "java.lang.ref.Cleaner"
    "java.lang.ref.ReferenceQueue"
    "java.lang.ref.WeakReference"
    "java.lang.reflect.AccessibleObject"
    "java.lang.reflect.Array"
    "java.lang.reflect.Field"
    "java.lang.reflect.Member"
    "java.lang.reflect.Method"
    "java.lang.reflect.Modifier"
    "java.math.BigDecimal"
    "java.math.BigInteger"
    "java.math.MathContext"
    "java.math.RoundingMode"
    "java.net.Authenticator"
    "java.net.BindException"
    "java.net.ConnectException"
    "java.net.CookieHandler"
    "java.net.CookieManager"
    "java.net.CookiePolicy"
    "java.net.CookieStore"
    "java.net.DatagramPacket"
    "java.net.DatagramSocket"
    "java.net.HttpCookie"
    "java.net.HttpURLConnection"
    "java.net.Inet4Address"
    "java.net.Inet6Address"
    "java.net.InetAddress"
    "java.net.InetSocketAddress"
    "java.net.PasswordAuthentication"
    "java.net.ProxySelector"
    "java.net.ServerSocket"
    "java.net.Socket"
    "java.net.SocketException"
    "java.net.SocketTimeoutException"
    "java.net.StandardProtocolFamily"
    "java.net.URI"
    "java.net.URISyntaxException"
    "java.net.URL"
    "java.net.URLClassLoader"
    "java.net.URLConnection"
    "java.net.URLDecoder"
    "java.net.URLEncoder"
    "java.net.UnixDomainSocketAddress"
    "java.net.UnknownHostException"
    "java.net.http.HttpClient"
    "java.net.http.HttpHeaders"
    "java.net.http.HttpRequest"
    "java.net.http.HttpResponse"
    "java.net.http.HttpTimeoutException"
    "java.net.http.WebSocket"
    "java.nio.ByteBuffer"
    "java.nio.ByteOrder"
    "java.nio.CharBuffer"
    "java.nio.DirectByteBuffer"
    "java.nio.DirectByteBufferR"
    "java.nio.MappedByteBuffer"
    "java.nio.channels.FileChannel"
    "java.nio.channels.ServerSocketChannel"
    "java.nio.channels.SocketChannel"
    "java.nio.charset.Charset"
    "java.nio.charset.CharsetEncoder"
    "java.nio.charset.CoderResult"
    "java.nio.charset.StandardCharsets"
    "java.nio.file.CopyOption"
    "java.nio.file.DirectoryNotEmptyException"
    "java.nio.file.FileAlreadyExistsException"
    "java.nio.file.FileSystem"
    "java.nio.file.FileSystems"
    "java.nio.file.FileVisitOption"
    "java.nio.file.FileVisitResult"
    "java.nio.file.FileVisitor"
    "java.nio.file.Files"
    "java.nio.file.LinkOption"
    "java.nio.file.NoSuchFileException"
    "java.nio.file.OpenOption"
    "java.nio.file.Path"
    "java.nio.file.PathMatcher"
    "java.nio.file.Paths"
    "java.nio.file.StandardCopyOption"
    "java.nio.file.StandardOpenOption"
    "java.nio.file.attribute.BasicFileAttributes"
    "java.nio.file.attribute.FileAttribute"
    "java.nio.file.attribute.FileTime"
    "java.nio.file.attribute.PosixFilePermission"
    "java.nio.file.attribute.PosixFilePermissions"
    "java.security.DigestInputStream"
    "java.security.KeyFactory"
    "java.security.KeyStore"
    "java.security.MessageDigest"
    "java.security.Provider"
    "java.security.SecureRandom"
    "java.security.Security"
    "java.security.cert.CertificateFactory"
    "java.security.cert.X509Certificate"
    "java.security.spec.PKCS8EncodedKeySpec"
    "java.sql.Date"
    "java.sql.Timestamp"
    "java.text.ParseException"
    "java.text.ParsePosition"
    "java.text.SimpleDateFormat"
    "java.time.Clock"
    "java.time.DateTimeException"
    "java.time.DayOfWeek"
    "java.time.Duration"
    "java.time.Instant"
    "java.time.LocalDate"
    "java.time.LocalDateTime"
    "java.time.LocalTime"
    "java.time.Month"
    "java.time.MonthDay"
    "java.time.OffsetDateTime"
    "java.time.OffsetTime"
    "java.time.Period"
    "java.time.Year"
    "java.time.YearMonth"
    "java.time.ZoneId"
    "java.time.ZoneOffset"
    "java.time.ZoneRegion"
    "java.time.ZonedDateTime"
    "java.time.format.DateTimeFormatter"
    "java.time.format.DateTimeFormatterBuilder"
    "java.time.format.DateTimeParseException"
    "java.time.format.DecimalStyle"
    "java.time.format.FormatStyle"
    "java.time.format.ResolverStyle"
    "java.time.format.SignStyle"
    "java.time.format.TextStyle"
    "java.time.temporal.ChronoField"
    "java.time.temporal.ChronoUnit"
    "java.time.temporal.IsoFields"
    "java.time.temporal.Temporal"
    "java.time.temporal.TemporalAccessor"
    "java.time.temporal.TemporalAdjuster"
    "java.time.temporal.TemporalAdjusters"
    "java.time.temporal.TemporalAmount"
    "java.time.temporal.TemporalField"
    "java.time.temporal.TemporalQuery"
    "java.time.temporal.WeekFields"
    "java.time.zone.ZoneRules"
    "java.util.ArrayDeque"
    "java.util.ArrayList"
    "java.util.Arrays"
    "java.util.Base64"
    "java.util.Collection"
    "java.util.Collections"
    "java.util.Comparator"
    "java.util.Date"
    "java.util.HashMap"
    "java.util.HashSet"
    "java.util.IdentityHashMap"
    "java.util.InputMismatchException"
    "java.util.Iterator"
    "java.util.List"
    "java.util.Locale"
    "java.util.Map"
    "java.util.MissingResourceException"
    "java.util.NoSuchElementException"
    "java.util.Optional"
    "java.util.Properties"
    "java.util.Random"
    "java.util.Scanner"
    "java.util.Set"
    "java.util.StringTokenizer"
    "java.util.TimeZone"
    "java.util.UUID"
    "java.util.WeakHashMap"
    "java.util.concurrent.ArrayBlockingQueue"
    "java.util.concurrent.BlockingQueue"
    "java.util.concurrent.Callable"
    "java.util.concurrent.CancellationException"
    "java.util.concurrent.CompletableFuture"
    "java.util.concurrent.CompletionException"
    "java.util.concurrent.ExecutionException"
    "java.util.concurrent.Executor"
    "java.util.concurrent.ExecutorService"
    "java.util.concurrent.ExecutorService"
    "java.util.concurrent.Executors"
    "java.util.concurrent.Future"
    "java.util.concurrent.FutureTask"
    "java.util.concurrent.LinkedBlockingQueue"
    "java.util.concurrent.ScheduledExecutorService"
    "java.util.concurrent.ScheduledFuture"
    "java.util.concurrent.ScheduledThreadPoolExecutor"
    "java.util.concurrent.Semaphore"
    "java.util.concurrent.ThreadFactory"
    "java.util.concurrent.ThreadPoolExecutor"
    "java.util.concurrent.TimeUnit"
    "java.util.concurrent.TimeoutException"
    "java.util.concurrent.atomic.AtomicInteger"
    "java.util.concurrent.atomic.AtomicLong"
    "java.util.concurrent.atomic.AtomicReference"
    "java.util.function.BiConsumer"
    "java.util.function.BiFunction"
    "java.util.function.Consumer"
    "java.util.function.Function"
    "java.util.function.Predicate"
    "java.util.function.Supplier"
    "java.util.jar.Attributes"
    "java.util.jar.JarEntry"
    "java.util.jar.JarFile"
    "java.util.jar.JarInputStream"
    "java.util.jar.JarOutputStream"
    "java.util.jar.Manifest"
    "java.util.regex.Matcher"
    "java.util.regex.Pattern"
    "java.util.stream.BaseStream"
    "java.util.stream.IntStream"
    "java.util.stream.Stream"
    "java.util.zip.CRC32"
    "java.util.zip.CheckedInputStream"
    "java.util.zip.Deflater"
    "java.util.zip.DeflaterInputStream"
    "java.util.zip.DeflaterOutputStream"
    "java.util.zip.GZIPInputStream"
    "java.util.zip.GZIPOutputStream"
    "java.util.zip.Inflater"
    "java.util.zip.InflaterInputStream"
    "java.util.zip.ZipEntry"
    "java.util.zip.ZipException"
    "java.util.zip.ZipFile"
    "java.util.zip.ZipInputStream"
    "java.util.zip.ZipOutputStream"
    "javax.crypto.Cipher"
    "javax.crypto.Mac"
    "javax.crypto.SecretKey"
    "javax.crypto.SecretKeyFactory"
    "javax.crypto.spec.GCMParameterSpec"
    "javax.crypto.spec.IvParameterSpec"
    "javax.crypto.spec.PBEKeySpec"
    "javax.crypto.spec.SecretKeySpec"
    "javax.net.ssl.HostnameVerifier"
    "javax.net.ssl.HttpsURLConnection"
    "javax.net.ssl.KeyManagerFactory"
    "javax.net.ssl.SSLContext"
    "javax.net.ssl.SSLException"
    "javax.net.ssl.SSLParameters"
    "javax.net.ssl.SSLSession"
    "javax.net.ssl.TrustManager"
    "javax.net.ssl.TrustManagerFactory"
    "javax.net.ssl.X509ExtendedTrustManager"
    "javax.net.ssl.X509TrustManager"])

(def base-dirs ["/Users/borkdude/.cache/clojure-lsp/jdk/java.base/"
                "/Users/borkdude/.cache/clojure-lsp/jdk/java.net.http/"
                "/Users/borkdude/.cache/clojure-lsp/jdk/java.sql/"
                "/Users/borkdude/dev/clojure/src/jvm"])

(defn class->file* [class]
  (let [parts (str/split class #"\.")
        parts* (butlast parts)
        file (last parts)
        file (str file ".java")]
    (concat parts* [file])))

(defn class->file [class]
  (some
   (fn [base]
     (let [f (apply io/file base
                   (class->file* class))]
       (when (.exists f) f)))
   base-dirs))

(comment
  (.exists (class->file "javax.net.ssl.X509TrustManager")))

(defn classes->files []
  (let [filez (mapv class->file classes)
        filez (mapv str filez)
        tmp-dir (fs/file (fs/temp-dir) "java-cache")]
    (kondo/run! {:lint filez
                 :cache-dir tmp-dir
                 :config {:analysis {:java-class-definitions true
                                     :java-member-definitions true}}})
    (fs/delete-tree "resources/clj_kondo/impl/cache/built_in/java")
    (fs/create-dirs "resources/clj_kondo/impl/cache/built_in/java")
    (doseq [f (fs/list-dir (fs/file tmp-dir "v1" "java"))]
      (fs/copy f "resources/clj_kondo/impl/cache/built_in/java"))
    tmp-dir))

(defn exec [_]
  (classes->files))

(comment
  (def tmp-dir (classes->files))
  (fs/file (fs/temp-dir) "java-cache")
  )
